﻿using System.Web.Mvc;
using System.Web;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Web.Security;
using CCTV.Logic;
using CCTV.Common;

public static class SiteRoles
{
    public static string List(params string[] roles)
    {
        return string.Join(", ", roles);
    }

    public const string Admin = "Admin";
    public const string User = "User";
}

public class CCTVAuthorize : AuthorizeAttribute
{
    //Property to allow array instead of single string.
    private string[] _authorizedRoles;
    public string[] AuthorizedRoles
    {
        get { return _authorizedRoles ?? new string[0]; }
        set { _authorizedRoles = value; }
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);
         
        //If its an unauthorized/timed out ajax request go to top window and redirect to logon.
        if (filterContext.Result is HttpUnauthorizedResult && filterContext.HttpContext.Request.IsAjaxRequest())
                    filterContext.Result = new JavaScriptResult() { Script = "top.location = '/Account/LogOn?Expired=1';" };
 
        //If authorization results in HttpUnauthorizedResult, redirect to error page instead of Logon page.
        if(filterContext.Result is HttpUnauthorizedResult)
            filterContext.Result = new RedirectResult("~/Error/Authorization");
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (httpContext == null)
            throw new ArgumentNullException("httpContext");
 
        if (!httpContext.User.Identity.IsAuthenticated)
            return false;
 
        //Bypass role check if user is Admin, prevents having to add Admin role across the whole project.
        if(httpContext.User.IsInRole("Admin"))
            return true;
 
        //If no roles are supplied to the attribute just check that the user is logged in.
        if(AuthorizedRoles.Length==0)
            return true;
 
        //Check to see if any of the authorized roles fits into any assigned roles only if roles have been supplied.
        if (AuthorizedRoles.Any(httpContext.User.IsInRole))
            return true;
 
        return false;
    }

}

public static class IPrincipalExtend
{
    public static bool HasAnyRole(this IPrincipal user, params string[] roles)
    {
        return roles.Any(user.IsInRole);
    }
}

public class CCTVRoleProvider : RoleProvider
{

    
    public override string ApplicationName
    {
        get { throw new NotImplementedException(); }
        set { throw new NotImplementedException(); }
    }

    public override void AddUsersToRoles(string[] usernames, string[] roleNames)
    {
        throw new NotImplementedException("AddUsersToRoles not implemented...");
 
    }

    public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
    {
        throw new NotImplementedException("Remove Users from roles not implemented...");
    }

    public override void CreateRole(string roleName)
    {
        throw new NotImplementedException("Create Role not implemented...");
    }

    /// <summary>
    /// Removes a role from the data source for the configured applicationName.
    /// </summary>
    /// <param name="roleName">The name of the role to delete.</param>
    /// <param name="throwOnPopulatedRole">If true, throw an exception if <paramref name="roleName"/> has one or more members and do not delete <paramref name="roleName"/>.</param>
    /// <returns>
    /// true if the role was successfully deleted; otherwise, false.
    /// </returns>
    public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
    {
        throw new NotImplementedException("Delete Role not implemented...");
    }

    /// <summary>
    /// Gets an array of user names in a role where the user name contains the specified user name to match.
    /// </summary>
    /// <param name="roleName">The role to search in.</param>
    /// <param name="usernameToMatch">The user name to search for.</param>
    /// <returns>
    /// A string array containing the names of all the users where the user name matches <paramref name="usernameToMatch"/> and the user is a member of the specified role.
    /// </returns>
    public override string[] FindUsersInRole(string roleName, string usernameToMatch)
    {
        throw new NotImplementedException("AddUsersToRoles not implemented...");
    }

    public override string[] GetAllRoles()
    {
        throw new NotImplementedException("Get All Roles not implemented...");
    }

    public override string[] GetRolesForUser(string username)
    {
        ApplicationUser usr = CommandManager.GetApplicationUsers().Where(x=> x.UserName == username).FirstOrDefault();
        if(usr == null)
            return null;
        return new string[] { usr.IsAdmin ? SiteRoles.Admin : SiteRoles.User };
    }

    public override string[] GetUsersInRole(string roleName)
    {
        throw new NotImplementedException("Get Users In Role not implemented");
    }

    public override bool IsUserInRole(string username, string roleName)
    {
        ApplicationUser usr = CommandManager.GetApplicationUsers().Where(x => x.UserName == username).FirstOrDefault();
        if (usr == null)
            return false;

        if (roleName == SiteRoles.Admin.ToString() && !usr.IsAdmin)
            return false;

        return true;
    }

    public override bool RoleExists(string roleName)
    {
        throw new NotImplementedException(" Role Exists not implemented...");
    }
}

public class CCCTVMembershipProvider : MembershipProvider
{
    public override MembershipUser CreateUser(string username,
       string password, string email, string passwordQuestion,
       string passwordAnswer, bool isApproved,
       object providerUserKey, out MembershipCreateStatus status)
    {
        throw new NotImplementedException();
    }

    public override MembershipUser GetUser(string username, bool userIsOnline)
    {
        throw new NotImplementedException();
    }

    public override bool ValidateUser(string username, string password)
    {
        return CommandManager.GetApplicationUsers().Where(
            x => x.UserName == username && x.Password == password).Any();
    }

    public override int MinRequiredPasswordLength
    {
        get { throw new NotImplementedException(); }
    }

    public override bool RequiresUniqueEmail
    {
        get { throw new NotImplementedException(); }
    }

    public override string ApplicationName
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            throw new NotImplementedException();
        }
    }

    public override bool ChangePassword(string username, string oldPassword, string newPassword)
    {
        throw new NotImplementedException();
    }

    public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
    {
        throw new NotImplementedException();
    }

    public override bool DeleteUser(string username, bool deleteAllRelatedData)
    {
        throw new NotImplementedException();
    }

    public override bool EnablePasswordReset
    {
        get { throw new NotImplementedException(); }
    }

    public override bool EnablePasswordRetrieval
    {
        get { throw new NotImplementedException(); }
    }

    public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
    {
        throw new NotImplementedException();
    }

    public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
    {
        throw new NotImplementedException();
    }

    public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
    {
        throw new NotImplementedException();
    }

    public override int GetNumberOfUsersOnline()
    {
        throw new NotImplementedException();
    }

    public override string GetPassword(string username, string answer)
    {
        throw new NotImplementedException();
    }

    public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
    {
        throw new NotImplementedException();
    }

    public override string GetUserNameByEmail(string email)
    {
        throw new NotImplementedException();
    }

    public override int MaxInvalidPasswordAttempts
    {
        get { throw new NotImplementedException(); }
    }

    public override int MinRequiredNonAlphanumericCharacters
    {
        get { throw new NotImplementedException(); }
    }

    public override int PasswordAttemptWindow
    {
        get { throw new NotImplementedException(); }
    }

    public override MembershipPasswordFormat PasswordFormat
    {
        get { throw new NotImplementedException(); }
    }

    public override string PasswordStrengthRegularExpression
    {
        get { throw new NotImplementedException(); }
    }

    public override bool RequiresQuestionAndAnswer
    {
        get { throw new NotImplementedException(); }
    }

    public override string ResetPassword(string username, string answer)
    {
        throw new NotImplementedException();
    }

    public override bool UnlockUser(string userName)
    {
        throw new NotImplementedException();
    }

    public override void UpdateUser(MembershipUser user)
    {
        throw new NotImplementedException();
    }
}
